package com.galen.manual.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.galen.manual.dto.SendSmsDTO;
import com.galen.manual.entity.SmsCode;
import com.galen.manual.mapper.SmsCodeMapper;
import com.galen.manual.service.SmsCodeService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Random;

/**
 * 短信验证码Service实现类
 */
@Service
public class SmsCodeServiceImpl implements SmsCodeService {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SmsCodeServiceImpl.class);

    private final SmsCodeMapper smsCodeMapper;
    private final Random random = new Random();

    // 验证码有效期（分钟）
    private static final int CODE_EXPIRE_MINUTES = 5;

    // 验证码长度
    private static final int CODE_LENGTH = 6;

    public SmsCodeServiceImpl(SmsCodeMapper smsCodeMapper) {
        this.smsCodeMapper = smsCodeMapper;
    }

    @Override
    public String sendSmsCode(SendSmsDTO sendSmsDTO, String ipAddress) {
        String phone = sendSmsDTO.getPhone();
        String businessType = "login"; // 默认为登录类型

        log.info("发送短信验证码请求: phone={}, businessType={}, ip={}", phone, businessType, ipAddress);

        // 验证手机号格式
        if (!isValidPhone(phone)) {
            throw new RuntimeException("手机号格式不正确");
        }

        // 检查是否还有有效的验证码
        if (hasValidCode(phone, businessType)) {
            log.info("手机号 {} 当前还有有效验证码，不重复发送", phone);
            return "当前验证码仍然有效，请查收短信";
        }

        // 生成新的验证码
        String code = generateCode();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expireTime = now.plusMinutes(CODE_EXPIRE_MINUTES);

        // 保存验证码到数据库
        SmsCode smsCode = new SmsCode();
        smsCode.setPhone(phone);
        smsCode.setCode(code);
        smsCode.setBusinessType(businessType);
        smsCode.setIpAddress(ipAddress);
        smsCode.setExpireTime(expireTime);
        smsCode.setUsed(false);
        smsCode.preInsert(); // 生成ID

        smsCodeMapper.insert(smsCode);

        // 这里应该调用短信服务商API发送短信
        // 为了演示，我们只是在日志中记录验证码
        sendSmsByProvider(phone, code, businessType);

        log.info("短信验证码发送成功: phone={}, code={}, expireTime={}", phone, code, expireTime);
        return "验证码发送成功";
    }

    @Override
    public boolean validateSmsCode(String phone, String code, String businessType) {
        log.info("验证短信验证码: phone={}, code={}, businessType={}", phone, code, businessType);

        LocalDateTime now = LocalDateTime.now();
        SmsCode smsCode = smsCodeMapper.selectValidCode(phone, businessType, now);

        if (smsCode == null) {
            log.warn("未找到有效的验证码: phone={}, businessType={}", phone, businessType);
            return false;
        }

        // 检查验证码是否匹配
        if (!code.equals(smsCode.getCode())) {
            log.warn("验证码不匹配: phone={}, expected={}, actual={}", phone, smsCode.getCode(), code);
            return false;
        }

        log.info("验证码验证成功: phone={}, code={}", phone, code);
        return true;
    }

    @Override
    public void markSmsCodeAsUsed(String phone, String code, String businessType) {
        log.info("标记验证码为已使用: phone={}, code={}, businessType={}", phone, code, businessType);

        LocalDateTime now = LocalDateTime.now();
        SmsCode smsCode = smsCodeMapper.selectValidCode(phone, businessType, now);

        if (smsCode != null && code.equals(smsCode.getCode())) {
            smsCodeMapper.markAsUsed(smsCode.getId(), now);
            log.info("验证码已标记为使用: phone={}, id={}", phone, smsCode.getId());
        }
    }

    @Override
    public void cleanExpiredCodes() {
        LocalDateTime expireTime = LocalDateTime.now();
        int cleanedCount = smsCodeMapper.cleanExpiredCodes(expireTime);
        if (cleanedCount > 0) {
            log.info("清理过期验证码完成，清理数量: {}", cleanedCount);
        }
    }

    @Override
    public boolean hasValidCode(String phone, String businessType) {
        LocalDateTime now = LocalDateTime.now();
        int count = smsCodeMapper.countValidCodes(phone, businessType, now);
        return count > 0;
    }

    /**
     * 生成验证码
     */
    private String generateCode() {
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

    /**
     * 验证手机号格式
     */
    private boolean isValidPhone(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 调用短信服务商发送短信
     * @param phone 手机号
     * @param code 验证码
     * @param businessType 业务类型
     */
    private void sendSmsByProvider(String phone, String code, String businessType) {
        // 实际项目中，这里应该调用阿里云、腾讯云等短信服务
        log.info("📱 [模拟短信发送] 手机号: {}, 验证码: {}, 业务类型: {}", phone, code, businessType);

        // 示例：调用阿里云短信服务
        /*
        try {
            DefaultProfile profile = DefaultProfile.getProfile(
                "cn-hangzhou", "your-access-key-id", "your-access-key-secret");
            IAcsClient client = new DefaultAcsClient(profile);

            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain("dysmsapi.aliyuncs.com");
            request.setSysVersion("2017-05-25");
            request.setSysAction("SendSms");
            request.putQueryParameter("RegionId", "cn-hangzhou");
            request.putQueryParameter("PhoneNumbers", phone);
            request.putQueryParameter("SignName", "你的签名");
            request.putQueryParameter("TemplateCode", "你的模板代码");
            request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");

            CommonResponse response = client.getCommonResponse(request);
            log.info("短信发送结果: {}", response.getData());
        } catch (Exception e) {
            log.error("短信发送失败", e);
            throw new RuntimeException("短信发送失败");
        }
        */
    }
}